﻿using System;
using System.Linq;
using NLog;
using Web.Bid.Models;
using Web.Bid.Extension;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;

namespace Web.Bid.Hubs
{
    public class AuctionHub : Hub
    {
        private readonly AuctionNotifier notifier;

        private static readonly Logger Logger = LogManager.GetLogger("log");

        internal readonly static ConnectionMapping<string> IpAddresses = new ConnectionMapping<string>();

        internal readonly static ConnectionMapping<string> Connections = new ConnectionMapping<string>();

        public AuctionHub() : this(AuctionNotifier.Instance) { }

        public AuctionHub(AuctionNotifier notifier)
        {
            this.notifier = notifier;
        }

        public void Bid(string input)
        {
            var now = DateTime.Now;
            var result = new SkResult<object>();

            var request = Context.Request;
            var identity = request.User.Identity;

            if (!identity.IsAuthenticated)
            {
                result.Message = "请先登录！";
                Clients.Caller.received(result);
                return;
            }
            if (!notifier.CheckTime(now))
            {
                result.Message = "未到竞拍时间！";
                Clients.Caller.received(result);
            }
            int id;
            if (!int.TryParse(input, out id) && id < 1)
            {
                result.Message = "参数不正确！";
                Clients.Caller.received(result);
                return;
            }
            var skIdentity = identity.SkIdentity();
            var userid = skIdentity.Id;
            var nickname = skIdentity.NickName;

            var username = identity.Name;
            var ipaddress = GetClientIp(request);

            result = notifier.Bid(id, userid, username, nickname, ipaddress);
            result.Extra = id;
            if (result.Status)
            {
                Clients.All.priceChanged(result);
            }
            else
            {
                Clients.Caller.priceChanged(result);
            }
        }

        public override Task OnConnected()
        {
            var now = DateTime.Now;
            if (notifier.CheckTime(now) && notifier.MarketState != MarketState.Open)
            {
                notifier.OpenMarket();
                Clients.Caller.marketOpened();
            }
            if ((now.Hour < notifier.OpenTime.Hour) && notifier.MarketState != MarketState.Closed)
            {
                notifier.CloseMarket();
                Clients.Caller.marketClosed();
            }

            var name = Context.User.Identity.Name;
            if(string.IsNullOrEmpty(name))
            {
                name = "匿名用户";
            }
            //if (Connections.GetConnections(name).Count() > notifier.ConnectionLimit)
            //{

            //}
            Connections.Add(name, Context.ConnectionId);

            var ipAddress = GetClientIp(Context.Request);
            IpAddresses.Add(ipAddress, name);
            
            return base.OnConnected();
        }

        public override Task OnDisconnected()
        {
            var name = Context.User.Identity.Name;
            if (string.IsNullOrEmpty(name))
            {
                name = "匿名用户";
            }
            Connections.Remove(name, Context.ConnectionId);

            var ipAddress = GetClientIp(Context.Request);
            IpAddresses.Remove(ipAddress, name);
            Logger.Trace("OnDisconnected:"+ Context.ConnectionId);
            return base.OnDisconnected();
        } 

       internal string GetClientIp(IRequest request)
        {
            var result = request.GetHttpContext().Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            if (string.IsNullOrEmpty(result))
            {
                result = request.GetHttpContext().Request.ServerVariables["REMOTE_ADDR"];
            }
            return result;
        }
    }
}